﻿namespace STLTypeVisualizer
{
	using System;
	using System.Diagnostics;
	using VisualGDBExpressions;

	class StringFilter : TypeListBasedExpressionFilter
	{
		public StringFilter(params string[] supportedTypes) : base(supportedTypes)
		{
		}

		static public string ParseString(string val)
		{
			string str = StaticExpressionFilter.RemoveQuotesAndUnescape(val.Trim());
			int len = str.Length;
			byte[] ar = new byte[len];
			for (int i = 0; i < len; ++i)
				ar[i] = (byte)str[i];

			return System.Text.Encoding.UTF8.GetString(ar);
		}

		protected override IExpression DoAttach(IExpression expr, IExpressionEvaluator evaluator)
		{
			string fullNameForEvaluator = expr.FullNameForEvaluator;
			ExpressionValue value2 = evaluator.EvaluateExpression(GetPointerString(evaluator, fullNameForEvaluator), null);
			if (value2 == null)
			{
				return null;
			}
			string val = value2.ToString();
			string Orgin = val;
			string addr = "";
			if (val.StartsWith("0x"))
			{
				int index = val.IndexOf(' ');
				if (index != -1)
				{
					addr = val.Substring(0, index);
					val = val.Substring(index + 1);
				}
			}

			// 截断干扰数据
			int indexStart = val.IndexOf("\"", 0);
			if (indexStart != -1)
			{
				int indexEnd = val.IndexOf("\"", indexStart + 1);
				if (indexEnd != -1)
					val = val.Substring(indexStart, indexEnd + 1 - indexStart);
			}

			StaticExpressionFilter filter = new StaticExpressionFilter(expr);
			string str = ParseString(val);
			string Value = string.Format("{0} \"{1}\"", addr, System.Text.RegularExpressions.Regex.Escape(str));
			filter.ValueOverride = new ExpressionValue.Custom(Value);

			if (val.StartsWith("\"") && val.EndsWith("\""))
			{
				filter.RawStringValueOverride = str;
			}
			value2 = evaluator.EvaluateExpression(GetLengthString(evaluator, fullNameForEvaluator), null);
			if (value2 is ExpressionValue.Integral)
			{
				ulong num2 = (value2 as ExpressionValue.Integral).Value;
				VirtualExpressionNode node1 = new VirtualExpressionNode("[实际成员]", "", expr.Children);
				node1.FixedValue = new ExpressionValue.Composite("{...}");
				VirtualExpressionNode actualMembersNode = node1;
				filter.ChildrenOverride = new ArrayChildProvider(evaluator, GetArrayPointerString(evaluator, fullNameForEvaluator), 0, (int)num2, actualMembersNode);
			}
			return filter;
		}

		protected virtual string GetPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return null;
		}
		protected virtual string GetLengthString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return null;
		}

		protected virtual string GetArrayPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return null;
		}
	}

	internal class GccStringFilter : StringFilter
	{
		static string[] textArray1 = new string[] { "std::basic_string<", "std::__cxx11::basic_string<" };
		public GccStringFilter() : base(textArray1)
		{
		}
		
		protected override string GetPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return $"({fullNameForEvaluator})._M_dataplus._M_p";
		}

		protected override string GetLengthString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return $"((unsigned *)({fullNameForEvaluator})._M_string_length)";
		}

		protected override string GetArrayPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			return $"({fullNameForEvaluator})._M_dataplus._M_p[{"{0}"}]";
		}
	}

	internal class ClangStringFilter : StringFilter
	{
		static string[] textArray1 = new string[] { "std::__1::basic_string<" };
		public ClangStringFilter() : base(textArray1)
		{

		}
		protected override string GetPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			ExpressionValue ValueIsLong = evaluator.EvaluateExpression($"({fullNameForEvaluator}).__r_.__value_.__s.__size_ & 0x01", null);
			if (ValueIsLong == null)
			{
				return null;
			}

			string s = ValueIsLong.ToString();
			if (s == "0")
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__s.__data_";
			}
			else
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__l.__data_";
			}
		}

		protected override string GetLengthString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			ExpressionValue ValueIsLong = evaluator.EvaluateExpression($"({fullNameForEvaluator}).__r_.__value_.__s.__size_ & 0x01", null);
			if (ValueIsLong == null)
			{
				return null;
			}

			string s = ValueIsLong.ToString();
			if (s == "0")
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__s.__size_ >> 1";
			}
			else
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__l.__size_";
			}
		}

		protected override string GetArrayPointerString(IExpressionEvaluator evaluator, string fullNameForEvaluator)
		{
			ExpressionValue ValueIsLong = evaluator.EvaluateExpression($"({fullNameForEvaluator}).__r_.__value_.__s.__size_ & 0x01", null);
			if (ValueIsLong == null)
			{
				return null;
			}

			string s = ValueIsLong.ToString();
			if (s == "0")
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__s.__data_[{"{0}"}]";
			}
			else
			{
				return $"({fullNameForEvaluator}).__r_.__value_.__l.__data_[{"{0}"}]";
			}
		}
	}

	internal class CharFilter : TypeListBasedExpressionFilter
	{
		static string[] textArray1 = new string[] { "const char *", "char *" };
		public CharFilter() : base(textArray1)
		{

		}

		protected override IExpression DoAttach(IExpression expr, IExpressionEvaluator evaluator)
		{
			string fullNameForEvaluator = expr.FullNameForEvaluator;
			ExpressionValue value2 = evaluator.EvaluateExpression($"({fullNameForEvaluator})", null);
			if (value2 == null)
			{
				return null;
			}

			string val = value2.ToString();
			string addr = "";
			if (val.StartsWith("0x"))
			{
				int index = val.IndexOf(' ');
				if (index != -1)
				{
					addr = val.Substring(0, index);
					val = val.Substring(index + 1);
				}
			}
			// 截断干扰数据
			int indexStart = val.IndexOf("\"", 0);
			if (indexStart != -1)
			{
				int indexEnd = val.IndexOf("\"", indexStart + 1);
				if(indexEnd != -1)
					val = val.Substring(indexStart, indexEnd + 1 - indexStart);
			}
			StaticExpressionFilter filter = new StaticExpressionFilter(expr);
			string str = StringFilter.ParseString(val);
			string Value = string.Format("{0} \"{1}\"", addr, System.Text.RegularExpressions.Regex.Escape(str));
			filter.ValueOverride = new ExpressionValue.Custom(Value);

			if (val.StartsWith("\"") && val.EndsWith("\""))
			{
				filter.RawStringValueOverride = str;
			}

			return filter;
		}
	}
}

